﻿using System;
using System.Collections.Generic;
using DemoPathfinding.Hotfix.Entitys;
using ETHotfix;
using ETModel;
using PF;
using UnityEngine;

namespace DemoPathfinding.Hotfix.Handlers {
    [MessageHandler(AppType.Map)]
    public class G2M_EnterMapHandler : AMRpcHandler<G2M_EnterMap, M2G_EnterMap> {
        protected override void Run(Session session, G2M_EnterMap message, Action<M2G_EnterMap> reply) {
            //抽象方法是同步的,需要操作异步代码,从这里转一手
            RunAsync(session, message, reply).Coroutine();
        }

        protected async ETVoid RunAsync(Session session, G2M_EnterMap message, Action<M2G_EnterMap> reply) {
            //当前玩家的回复
            M2G_EnterMap response = new M2G_EnterMap();

            var mapUnitsComp = Game.Scene.GetComponent<UnitsComponent>();
            var cfgComp = Game.Scene.GetComponent<ConfigComponent>();

            try {
                //!!! 玩家成功连接到Map服务器,必须调用本方法初始化!
                var mapPlayer = await session.MapPlayerLoginSuccess(message.GateSessionInstanceId, null);

                //给当前玩家加一个单位
                var pos = new Vector3(-10, 0, -10);
                GameUnit unit = ComponentFactory.CreateWithId<GameUnit, long>(IdGenerater.GenerateId(), mapPlayer.Id);
                unit.AddComponent<MoveComponent>();//加入持续移动计算组件
                var unitPathComp = unit.AddComponent<UnitPathComponent>();
                //把寻路结果广播给客户端
                unitPathComp.OnPathfindingBroadcast += UnitPathComp_OnPathfindingBroadcast;
                unit.Position = pos;
                //加入到当前玩家的单位管理中
                mapPlayer.AddSelfUnit(unit);


                //回复当前客户端
                response.MapPlayerInstanceId = mapPlayer.InstanceId;
                var units = mapUnitsComp.GetAll();
                foreach (var u in units) {
                    response.Units.Add((u as GameUnit).BuildUnitInfo());
                }
                response.SelfUnitIds.Add(unit.Id);
                reply(response);

                //给其他已经在线的玩家的回复
                M2C_PlayerEnterMap playerEnterMsg = new M2C_PlayerEnterMap();
                playerEnterMsg.NewUnits.Add(unit.BuildUnitInfo());
                //MessageHelper.Broadcast(playerEnterMsg, mapPlayer.Id);
                playerEnterMsg.MapBroadcastAllPlayers(mapPlayer.Id);

            } catch (Exception e) {
                ReplyError(response, e, reply);
            }
        }

        private void UnitPathComp_OnPathfindingBroadcast(Unit unit, List<Vector3> path, int index, int offset) {

            Vector3 unitPos = unit.GetPosition();
            M2C_PathfindingResult m2CPathfindingResult = new M2C_PathfindingResult();
            m2CPathfindingResult.X = unitPos.x;
            m2CPathfindingResult.Y = unitPos.y;
            m2CPathfindingResult.Z = unitPos.z;
            m2CPathfindingResult.UnitId = unit.Id;

            for (int i = 0; i < offset; ++i) {
                if (index + i >= path.Count) {
                    break;
                }
                Vector3 v = path[index + i];
                m2CPathfindingResult.Xs.Add(v.x);
                m2CPathfindingResult.Ys.Add(v.y);
                m2CPathfindingResult.Zs.Add(v.z);
            }
            //MessageHelper.Broadcast(m2CPathfindingResult);
            m2CPathfindingResult.MapBroadcastAllPlayers();
        }
    }
}